App = window.App || (function () {
	var app = {};
	try {
		app.name = 'app';
		app.version = 1.0;
		app.emptyFn = function () { };
		app.config = {
			name: '',
			debug: false,
			baseUrl: ''
		};

		app.init = function (config) {
			app.extend(app.config, config);
			app.name = app.config.name;
			app.debug = app.config.debug;
			app.baseUrl = app.config.baseUrl;
			App.loadScripts(app.config.scripts, function () {
				app.require(app.config.modules, function () {
					app.isUndefined(app.config.success) || app.config.success();
				});
			});
		};

		app.require = function (r, callback) {
			if (typeof r === 'string') {
				var url = toModuleUrl(r);
				app.loadScript(url, function (result) {
					app.isUndefined(callback) || callback(result);
				});
			} else {
				var count = r.length;
				for (var i = 0; i < count; i++) {
					r[i] = toModuleUrl(r[i]);
				}

				app.loadScripts(r, function (result) {
					app.isUndefined(callback) || callback(result);
				});
			}
		};

		app.define = function (name, require, obj) {
			if (!app[name]) {
				app.require(require, function (success) {
					if (success) {
						app[name] = obj;
						if (!app.isUndefined(app[name].complited)) {
							app[name].complited();
						}
					}
				});
			}
		};

		app.isUndefined = function (obj) {
			return typeof obj == 'undefined';
		};

		app.isSupported = function () {
			var Browser = function (b, v) { return { browser: b, version: v }; };
			var support = [new Browser('webkit', 8),
						   new Browser('firefox', 3.6),
						   new Browser('safari', 5),
						   new Browser('opera', 11),
						   new Browser('msie', 9),
						   new Browser('ipad', 0)];
			var result = false;

			$.each(support, function (i, item) {
				result = result || (bowser[item.browser] && bowser.version >= item.version);
			});

			return result && !bowser.mobile && Modernizr.canvas && Modernizr.websockets;
		};

		app.dom = {
			body: document.body,
			head: document.getElementsByTagName('head')[0],
			all: document.all
		};

		app.extend = function (destination, source) {
			for (var property in source) {
				if (source[property] && source[property].constructor &&
				 source[property].constructor === Object) {
					destination[property] = destination[property] || {};
					arguments.callee(destination[property], source[property]);
				} else {
					destination[property] = source[property];
				}
			}
			return destination;
		};

		function toModuleUrl(module) {
			return app.config.baseUrl
				+ 'modules/{module}.module{.min}.js'
				.replace('{module}', module)
				.replace('{.min}', App.config.debug ? '' : '.min');
		}

		app.loadScripts = function (urls, callback) {
			if (app.isUndefined(urls) || urls.length == 0) {
				app.isUndefined(callback) || callback(true);
				return;
			}

			var count = urls.length, n = 0;

			for (var i = 0; i < count; i++) {
				app.loadScript(urls[i], callbackLocal);
			}

			function callbackLocal(result) {
				n++;
				if (n < count) return;
				app.isUndefined(callback) || callback(result);
			}

		};

		app.loadScript = function (path, callback) {

			if (document.querySelector('script[src="' + path + '"]') != null) {
				callback(true);
				return;
			}

			var done = false;
			var script = document.createElement('script');

			script.onload = handleLoad;
			script.onreadystatechange = handleReadyStateChange;
			script.onerror = handleError;

			app.dom.head.appendChild(script);

			script.src = path;

			function handleLoad() {
				if (!done) {
					done = true;
					callback(true);
				}
			}

			function handleReadyStateChange() {
				var state;

				if (!done) {
					state = script.readyState;
					if (state === 'complete') {
						handleLoad();
					}
				}
			}

			function handleError() {
				if (!done) {
					done = true;
					callback(false);
				}
			}
		};

	} catch (e) {
		console.error('app.js', e);
	}
	return app;
})();